package com.acme.bankapp.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.service.bank.BankService;
import com.acme.exceptions.ClientDuplicateException;
import com.acme.exceptions.ClientNotExistException;
import com.acme.exceptions.NotEnoughFundsException;

public class BankServer {
	Bank bank;
	ServerSocket providerSocket = null;
	Socket connection = null;
	ObjectOutputStream out;
	ObjectInputStream in;
	String message;
	Client clientConnected = null;
	
	public BankServer(Bank bank) {
		this.bank = bank;
	}
	
	public void run() throws ClientDuplicateException, ClientNotExistException, NumberFormatException, NotEnoughFundsException {
		try {
			providerSocket = new ServerSocket(1234,10);
			System.out.println("Waiting for connection");
			connection = providerSocket.accept();
			System.out.println("Coonection received from: " + 
				connection.getInetAddress().getHostName());
			out = new ObjectOutputStream(connection.getOutputStream());
			out.flush();
			in = new ObjectInputStream(connection.getInputStream());
			sendMessage("connection succesfull!");
			try {
				message = (String)in.readObject();
				System.out.println("client>" + message);
			} catch (ClassNotFoundException cnf) {
				cnf.printStackTrace();
			}
			do {
				try {
					message = (String)in.readObject();
					this.process(message);
				} catch (ClassNotFoundException cnf) {
					cnf.printStackTrace();
				}
			} while (!message.equals("bye"));
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} finally {
			try {
				in.close();
				out.close();
				providerSocket.close();
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
	}
	
	void process(String receivedMessage) throws ClientDuplicateException, ClientNotExistException, NumberFormatException, NotEnoughFundsException {
		System.out.println("server>" + receivedMessage);
		if(receivedMessage.matches("^add " + Bank.regLine.substring(1))) {
			this.bank.addClient(receivedMessage.substring(4));
		} else if (receivedMessage.equals("print balance")) {
			BankService.printBalance(this.bank);
		} else if (receivedMessage.matches("^modify client ([-+]?[0-9]*) by ([-+]?[0-9]*\\.?[0-9]*)$")) {
			Pattern pattern = Pattern.compile("^modify client ([-+]?[0-9]*) by ([-+]?[0-9]*\\.?[0-9]*)$");
			Matcher matcher = pattern.matcher(receivedMessage);
			while(matcher.find()) {
				BankService.modifyBank(this.bank, Integer.parseInt(matcher.group(1)), Double.parseDouble(matcher.group(2)));				
			}
		}
	}
	
	void sendMessage (final String msg) {
		try {
			out.writeObject(msg);
			out.flush();
			System.out.println("server>" + msg);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}
